import pdfplumber
from typing import Optional
from book import Book, Page, Content, ContentType, TableContent, ImageContent, Row, Cell
from translator.exceptions import PageOutOfRangeException
from utils import LOG
from pdfminer.image import ImageWriter
from pdfminer.layout import LTImage
import io
import os

class PDFParser:
    def __init__(self):
        #段落判断，如果行间距大于20 就算新的段落 TODO 这里不太好
        self.line_spacing_threshold=50
        pass

    def parse_pdf(self, pdf_file_path: str, pages: Optional[int] = None) -> Book:
        book = Book(pdf_file_path)

        with pdfplumber.open(pdf_file_path) as pdf:
            if pages is not None and pages > len(pdf.pages):
                raise PageOutOfRangeException(len(pdf.pages), pages)

            pages_to_parse = pdf.pages[:pages] if pages else pdf.pages

            for page_number,pdf_page in enumerate(pages_to_parse):
                page = Page()

                char_data = pdf_page.chars
                # 获取所有表格
                all_tables = pdf_page.find_tables()
                # 提取表格边界
                table_bounds = self._get_table_bounds(all_tables)
                # 解析表格内容
                tables = self._parse_tables_content(all_tables)

                # 处理文本内容
                for block in self._group_chars_into_blocks(char_data):
                    # 过滤掉在表格边界内的文本
                    if not self._is_within_table(block["position"], table_bounds):
                        text_content = Content(
                            content_type=ContentType.TEXT,
                            original=block["text"],
                            font_size=block["font_size"],
                            is_bold=block["is_bold"],
                            position=block["position"],
                        )
                        page.add_content(text_content)
                        LOG.debug(
                            f"[Text Block: {block['text']}, Position: {block['position']}]"
                        )

                # 处理表格内容
                if tables:
                    for tableContent in tables:
                        LOG.debug(f"[Table Found]\n{tableContent}")
                        page.add_content(tableContent)
                    
                
                for img_index, image_info in enumerate(pdf_page.images):
                    bbox = (image_info["x0"], image_info["top"], image_info["x1"], image_info["bottom"])
                    #bbox = [image_info['x0'], pdf_page.cropbox[3]-image_info['y1'],  image_info['x1'], pdf_page.cropbox[3]-image_info['y0']]
                    parent_dir = os.path.dirname(pdf_file_path)
                    image_filename = f"page_{page_number + 1}_image_{img_index + 1}.png"
                    cropped_page = pdf_page.crop(bbox)
                    img_obj = cropped_page.to_image()
                    image_path = parent_dir+"/"+image_filename
                    img_obj.save(image_path)
                    # 提取图片数据
                    image_content = ImageContent(
                        image_path=image_path,
                        image_name=image_filename,
                        width=image_info["width"],
                        height=image_info["height"],
                        position=(image_info["x0"], image_info["top"], image_info["x0"] + image_info["width"], image_info["top"] + image_info["height"])
                    )
                    page.add_content(image_content)

                    print(f"Saved image {image_path}")

                # TODO 根据 y 轴坐标排序块内容
                
                book.add_page(page)

        return book

    def _group_chars_into_blocks(self, char_data):
        """
        将字符数据分组为文本块，并保留格式和布局信息。
        """
        current_block = None

        for char in char_data:
            font_size = char["size"]
            is_bold = "Bold" in char["fontname"]
            position = (char["x0"], char["top"],char["x0"]+char["width"],char["top"]+char["height"])
            if current_block is None or self._is_new_block(
                current_block, font_size, is_bold, position
            ):
                if current_block:
                    yield current_block
                current_block = {
                    "text": char["text"],
                    "font_size": font_size,
                    "is_bold": is_bold,
                    "position": position,
                }
            else:
                current_block["text"] += char["text"]
                x1 = char["x0"]+char["width"]
                y1 = char["top"]+char["height"]
                current_block["position"] = (current_block["position"][0],current_block["position"][1],x1,y1)  # 更新 x1

        if current_block:
            yield current_block

    def _is_new_block(self, current_block, font_size, is_bold, position):
        """
        检查是否需要开始一个新的文本块。
        """
        line_spacing = abs(current_block["position"][1] - position[1])
        return (
            font_size != current_block["font_size"]
            or is_bold != current_block["is_bold"]
            or line_spacing > (font_size + self.line_spacing_threshold)
        )

    def _is_within_table(self, position, table_bounds):
        """
        检查文本块是否在表格区域内。
        """
        x, y,x1,y1 = position
        for bbox in table_bounds:
            # LOG.debug(f"[判断 bbox {bbox} ")
            if bbox[0] <= x <= bbox[2] and bbox[1] <= y <= bbox[3]:
                # LOG.debug(f"[判断 x{x}, y:{y} ")
                return True
        return False

    def _get_table_bounds(self, tables):
        """
        获取所有表格的边界，用于从文本中剔除表格内容。
        """
        bounds = []

        for table in tables:
            # Initialize bounds for the current table
            bounds.append(table.bbox)
        return bounds

    def _parse_tables_content(self, all_tables):
        """
        解析表格文本内容，单元格长宽
        """
        tables = []

        for table in all_tables:

            table_content = table.extract()
            table_rows = []
            for row_index, row in enumerate(table.rows):
                row_content = Row()
                
                for cell_index, cell in enumerate(row.cells):
                    x1, y1, x2, y2 = cell
                    # 计算单元格的宽度和高度
                    cell_width = x2 - x1
                    cell_height = y2 - y1
                    cell_content = table_content[row_index][cell_index]
                    cell = Cell(
                        original=cell_content, width=cell_width, heigth=cell_height
                    )
                    row_content.add_cell(cell)
                table_rows.append(row_content)
            
            table_content = TableContent(
                data=table_rows,
                position=table.bbox,
            )
            tables.append(table_content)
        return tables
